/*
 * ClientManager.cpp
 *
 *  Created on: 2012-3-25
 *      Author: zgx
 */

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/socket.h>

#include <stdlib.h>
#include <string.h>

extern "C" {
#include "util/Log.h"
}
#include "ClientManager.h"
#include "RtpClient.h"

extern CRtpClient* gBsuClient;

CClientManager::CClientManager() {

}

CClientManager::~CClientManager() {
}

void CClientManager::startAll() {// called externally, when RTP server received a frame which is a SPS frame.
    ClientListIterator it, tmp;
    sListCond.Lock();
    for (it = mClientList.begin(); it != mClientList.end(); it++) {
        if ((*it)->state == STATE_PENDDING) {
            (*it)->state = STATE_RUNNING;
            mRunningSize++;
            mPenddingSize--;
            break;
        }
    }
    sListCond.Unlock();
}

void CClientManager::sendToClient(unsigned char* buf, unsigned int len) {
    ClientListIterator it, tmp;
    //TODO test
//    static int testmp=0;
//    if(testmp>5)
//        return;

    sListCond.Lock();
    for (it = mClientList.begin(); it != mClientList.end();) {
        if ((*it)->state == STATE_RUNNING) {
            //            WriteLog(LOG_INFO,"send buf to client! len = %d",len);
            printf("send buf to client! len = %d\n", len);
            printf("type = %d\n",(*it)->type);
            if ((*it)->type == TYPE_TCP) {
                if (-1 == send((*it)->sock, buf, len, 0)) {
                    (*it)->state = STATE_UNKNOWN;
                    mRunningSize--;
                }
            } else {
                //                struct sockaddr_in addr;
                if (-1 == send((*it)->sock, buf, len, 0)) {//, (struct sockaddr*)&addr, addr_len
                    (*it)->state = STATE_UNKNOWN;
                    mRunningSize--;
                    //TODO test
                }
            }
            it++;
        } else if ((*it)->state == STATE_STOP || (*it)->state == STATE_UNKNOWN) {
            // simply, just delete it
            tmp = it;
            it++;
            mClientList.erase(tmp);
            mTotalSize--;
            delete *tmp;
            // TODO, complexly, reconnect to client that the state is unknown and do nothing that the state is stop,
            // if reconnect true then change state to pend,
            // else tell the RTSP server the client maybe disconnected.

        } else {
            it++;
        }
    }
    sListCond.Unlock();
}

int CClientManager::createNewClient(int cmd, int type, int port,
        char* strClientAddr, char* session) {

    WriteLog(
            LOG_INFO,
            "createNewClient(command = %d, type = %d, port = %d, strClientAddr = %s, session = %s)",
            cmd, type, port, strClientAddr, session);
    printf(
            "createNewClient(command = %d, type = %d, port = %d, strClientAddr = %s, session = %s)",
            cmd, type, port, strClientAddr, session);

    PClientNode pClientNode = new ClientNode();
    pClientNode->cmd = cmd;
    pClientNode->port = port;
    pClientNode->type = type;
    pClientNode->state = STATE_NEW;
    strcpy(pClientNode->strClientAddr, strClientAddr);
    strcpy(pClientNode->session, session);
    return createNewClient(pClientNode);
}

int CClientManager::manageClient(int cmd, char* strSession) {
    if (cmd == CMD_SETUP) {

    } else if (cmd == CMD_PLAY) {
        playClient(strSession);
    } else if (cmd == CMD_PAUSE) {
        pauseClient(strSession);
    } else if (cmd == CMD_STOP) {
        stopClient(strSession);
    } else if (cmd == CMD_EXIT) {
        removeClient(strSession);
    } else if (cmd == CMD_CAMERA_UP) {
        camera_cmd(gRtpClient->getServerIP(), 1);
    } else if (cmd == CMD_CAMERA_DOWN) {
        camera_cmd(gRtpClient->getServerIP(), 2);
    } else if (cmd == CMD_CAMERA_LEFT) {
        camera_cmd(gRtpClient->getServerIP(), 3);
    } else if (cmd == CMD_CAMERA_RIGHT) {
        camera_cmd(gRtpClient->getServerIP(), 6);
    }

    return 0;
}

/*************************************************************
 *                      private
 *************************************************************/
int CClientManager::createNewClient(const PClientNode &pClientNode) {
    pClientNode->sock = connectToClient(pClientNode->strClientAddr,
            pClientNode->port, pClientNode->type);
    if (pClientNode->sock >= 0) {
        sListCond.Lock();
        mClientList.push_back(pClientNode);
        mTotalSize++;
        mNewSize++;
        sListCond.Unlock();
        return 0;
    } else {
        return -1;
    }
}

int CClientManager::removeClient(char* session) {
    ClientListIterator it, tmp;
    sListCond.Lock();
    for (it = mClientList.begin(); it != mClientList.end();) {
        if (strncmp((*it)->session, session, strlen(session)) == 0) {
            tmp = it;
            it++;
            decrease((*tmp)->state);
            mClientList.erase(tmp);
            mTotalSize--;
            delete *tmp;
            break;
        } else {
            it++;
        }
    }
    sListCond.Unlock();
    return 0;
}

int CClientManager::playClient(char* session) {
    ClientListIterator it, tmp;
    sListCond.Lock();
    for (it = mClientList.begin(); it != mClientList.end(); it++) {
        if (strncmp((*it)->session, session, strlen(session)) == 0) {
            if ((*it)->state != STATE_RUNNING && (*it)->state != STATE_UNKNOWN) {
                decrease((*it)->state);
                (*it)->state = STATE_PENDDING;
                mPenddingSize++;
                break;
            }
        }
    }
    sListCond.Unlock();
    return 0;
}

int CClientManager::pauseClient(char* session) {
    ClientListIterator it, tmp;
    sListCond.Lock();
    for (it = mClientList.begin(); it != mClientList.end(); it++) {
        if (strncmp((*it)->session, session, strlen(session)) == 0) {
            if ((*it)->state != STATE_STOP) {
                decrease((*it)->state);
                (*it)->state = STATE_PAUSE;
                mPauseSize++;
                break;
            }
        }
    }
    sListCond.Unlock();
    return 0;
}

int CClientManager::stopClient(char* session) {
    ClientListIterator it, tmp;
    sListCond.Lock();
    for (it = mClientList.begin(); it != mClientList.end(); it++) {
        if (strncmp((*it)->session, session, strlen(session)) == 0) {
            decrease((*it)->state);
            (*it)->state = STATE_STOP;
            break;
        }
    }
    sListCond.Unlock();
    return 0;
}

int CClientManager::connectToClient(char* strClientAddr, int port, int type) {
    int sock = -1;

    int dataType;
    if (type == TYPE_TCP) {
        dataType = SOCK_STREAM;
    } else {
        dataType = SOCK_DGRAM;
    }

    if ((sock = socket(AF_INET, dataType, 0)) < 0) {
        perror("socket");
        return -1;
    }

    struct sockaddr_in addr;
    if (type == TYPE_TCP) {
        // init sockaddr_in
        bzero(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(strClientAddr);
        // Try to connect to server
        if (connect(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
            perror("connect");
            return -1;
        }
        return sock;
    } else {
        // init sockaddr_in
        bzero(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(strClientAddr);
        //        addr.sin_addr.s_addr = htonl(INADDR_ANY);

        // Try to connect to server
        if (connect(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
            perror("connect");
            return -1;
        }
        //        printf("begin send 1234567890\n");
        //        send(sock,"1234567890",10,0);
        //        printf("end send 1234567890\n");
        return sock;
    }
}

#define BUFFLEN 1024                            //缓冲区的长度
#define SERVER_PORT 81                          //绑定的端口
int camera_cmd(const char *serverAddr,int cmd) {
    int s; //服务器套接字文件描述符
    struct sockaddr_in server; //服务器地址结构
    time_t now; //时间
    char buff[BUFFLEN]; //收发数据缓冲区
    int n = 0;

    /*建立TCP的套接字***/
    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0) //出错处理
    {
        printf("socket error\n");
        perror("s");
    }
    /****服务器地址的初始化*****/
    memset(&server, 0, sizeof(server)); //清零
    server.sin_family = AF_INET; //AF_INET协议族
    inet_pton(AF_INET, serverAddr, &server.sin_addr);
    server.sin_port = htons(SERVER_PORT); //服务器的端口

    /*连接服务器*/
    int err = connect(s, (struct sockaddr*) &server, sizeof(server));
    if (err < 0) //出错处理
    {
        printf("connect error\n");
        perror("err");
    }
    memset(buff, 0, BUFFLEN); //清零
    sprintf(buff,"GET /decoder_control.cgi?&loginuse=&loginpas=&command=%d&onestep=0 HTTP/1.1\r\n"
                "Host: %s:%d\r\n\r\n",cmd,serverAddr,SERVER_PORT);

    /*发送数据*/
    printf("send:%s\n", buff);
    send(s, buff, strlen(buff), 0);
    memset(buff, 0, BUFFLEN); //清零
    /*接收数据*/
    n = recv(s, buff, BUFFLEN, 0);
    printf("recv:%s\n", buff);
    /*打印数据*/
    if (n > 0) {
        printf("TIME:%s", buff);
    }
    close(s);
    return 0;
}

